home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / svgakt50.zip / SRC / SVGAKIT / SVGAC.C < prev    next >
C/C++ Source or Header  |  1994-08-23  |  30KB  |  881 lines

  1. /****************************************************************************
  2. *
  3. *                              The SuperVGA Kit
  4. *
  5. *                   Copyright (C) 1994 SciTech Software
  6. *                           All rights reserved.
  7. *
  8. * Filename:     $RCSfile: svgac.c $
  9. * Version:      $Revision: 1.1 $
  10. *
  11. * Language:     ANSI C
  12. * Environment:  IBM PC (MSDOS) Real Mode and 16/32 bit Protected Mode.
  13. *
  14. * Description:  Simple library to collect together the functions in the
  15. *               SuperVGA test library for use in other C programs. The
  16. *               support is reasonably low level, so you can do what you
  17. *               want. The set of routines in this source file are general
  18. *               SuperVGA routines and are independant of the video mode
  19. *               selected.
  20. *
  21. *               MUST be compiled in the large model.
  22. *
  23. * $Id: svgac.c 1.1 1994/08/22 12:27:00 kjb release $
  24. *
  25. ****************************************************************************/
  26.  
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <dos.h>
  31. #include "pmode.h"
  32. #include "svga.h"
  33. #include "vesavbe.h"
  34.  
  35. /*---------------------------- Global Variables ---------------------------*/
  36.  
  37. #define MAXMODES    50              /* Maximum modes available in list  */
  38.  
  39. int     maxx,maxy,memory;
  40. long    maxcolor,defcolor;
  41. int     maxpage,bytesperline,bytesperpixel;
  42. uchar    redMask,greenMask,blueMask;
  43. int        redPos,redAdjust;
  44. int        greenPos,greenAdjust;
  45. int        bluePos,blueAdjust;
  46. bool    twobanks = false;
  47. short   modeList[MAXMODES];
  48. char    OEMString[80];
  49.  
  50. bool    extendedflipping = false;   /* True for extended flipping enable*/
  51. bool    widedac = false;            /* True for 8 bit DAC support        */
  52. int     oldMode = 0x3;              /* Old video mode number            */
  53. bool    old50Lines;                 /* Was old mode 80x50?              */
  54. int     curBank;                    /* Current read/write bank          */
  55. int     bankShift;                     /* Bank granularity adjust factor   */
  56. long    pagesize;                   /* Page size for current mode       */
  57. void    *bankSwitch;                   /* Pointer to bank switch routine   */
  58. void    *writeBank;                    /* Pointer to write bank routine    */
  59. void    *readBank;                    /* Pointer to read bank routine     */
  60. uint    VESABuf_sel;                /* Selector for VESABuf (1k size)    */
  61. uint    VESABuf_off;                /* Offset for VESABuf (1k size)        */
  62. uint    VESABuf_rseg;                /* Real mode segment of VESABuf        */
  63. uint    VESABuf_roff;                /* Real mode offset of VESABuf        */
  64. int        oldFS;                        /* Old value of FS selector            */
  65. void     (_cdecl *line)(int x1,int y1,int x2,int y2,long color);
  66. void     (_cdecl *putPixel)(int x,int y,long color);
  67. void     (_cdecl *clear)(long color);
  68.  
  69. extern    uchar font8x16[];            /* Bitmap font definition            */
  70.  
  71. /*----------------------------- Implementation ----------------------------*/
  72.  
  73. /* Declare all video mode dependent routines */
  74.  
  75. int _cdecl _setFS(uint sel);
  76. void _cdecl _clear16(long color);
  77. void _cdecl _clear256(long color);
  78. void _cdecl _clear32k(long color);
  79. void _cdecl _clear16m(long color);
  80. void _cdecl _clear4G(long color);
  81. void _cdecl _putPixel16(int x,int y,long color);
  82. void _cdecl _putPixel256(int x,int y,long color);
  83. void _cdecl _putPixel32k(int x,int y,long color);
  84. void _cdecl _putPixel16m(int x,int y,long color);
  85. void _cdecl _putPixel4G(int x,int y,long color);
  86. void _cdecl _line16(int x1,int y1,int x2,int y2,long color);
  87. void _cdecl _line256(int x1,int y1,int x2,int y2,long color);
  88. void _cdecl _line32k(int x1,int y1,int x2,int y2,long color);
  89. void _cdecl _line16m(int x1,int y1,int x2,int y2,long color);
  90. void _cdecl _line4G(int x1,int y1,int x2,int y2,long color);
  91. void _cdecl _EMU_line(int x1,int y1,int x2,int y2,long color);
  92.  
  93. PRIVATE void CallVBE(RMREGS *regs, void *buffer, int size)
  94. /****************************************************************************
  95. *
  96. * Function:        CallVBE
  97. * Parameters:    regs    - Registers to load when calling VBE
  98. *                buffer    - Buffer to copy VBE info block to
  99. *                size    - Size of buffer to fill
  100. *
  101. * Description:    Calls the VESA VBE and passes in a buffer for the VBE to
  102. *                store information in, which is then copied into the users
  103. *                buffers space. This works in protected mode as the buffer
  104. *                passed to the VESA VBE is allocated in conventional
  105. *                memory, and is then copied into the users memory block.
  106. *
  107. ****************************************************************************/
  108. {
  109.     RMSREGS    sregs;
  110.  
  111.     sregs.es = VESABuf_rseg;
  112.     regs->x.di = VESABuf_roff;
  113.     PM_int86x(0x10, regs, regs, &sregs);
  114.     PM_memcpynf(buffer, VESABuf_sel, VESABuf_off, size);
  115. }
  116.  
  117. PRIVATE void exitSuperVGA(void)
  118. /****************************************************************************
  119. *
  120. * Function:        exitSuperVGA
  121. *
  122. * Description:    Cleans up after using the SuperVGA library. We need to
  123. *                de-allocate any real mode memory that we have allocated
  124. *                during the operation of the library, and any protected
  125. *                mode pointers etc.
  126. *
  127. ****************************************************************************/
  128. {
  129.     PM_freeRealSeg(VESABuf_sel,VESABuf_off);
  130. }
  131.  
  132. PUBLIC int initSuperVGA(bool enableSpecialFeatures)
  133. /****************************************************************************
  134. *
  135. * Function:     initSuperVGA
  136. * Parameters:    enableSpecialFeatures    - True to enable enhanced features
  137. * Returns:      VBE version number for the SuperVGA (0 if no SuperVGA).
  138. *
  139. * Description:  Detects if a VESA VBE compliant SuperVGA is out there, and
  140. *               initialises the library if one is. The VBE version number
  141. *               is specified with the major version number in the high
  142. *               byte and the minor version number in the low byte. So
  143. *               version 1.2 is the number 0x102.
  144. *
  145. ****************************************************************************/
  146. {
  147.     VgaInfoBlock    vgaInfo;
  148.     ModeInfoBlock   modeInfo;
  149.     RMREGS          regs;
  150.     short            *p;
  151.     uint            sel,off;
  152.     ulong            addr;
  153.     int                i;
  154.  
  155.     /* Allocate a global buffer for communicating with the VESA VBE */
  156.     if (!PM_allocRealSeg(1024, &VESABuf_sel,  &VESABuf_off, &VESABuf_rseg,
  157.             &VESABuf_roff)) {
  158.         fprintf(stderr, "PM_allocRealSeg failed!\n");
  159.         exit(1);
  160.         }
  161.  
  162.     regs.x.ax = 0x4F00;     /* Get SuperVGA information */
  163.     CallVBE(®s, &vgaInfo, sizeof(vgaInfo));
  164.     if (regs.x.ax != 0x004F)
  165.         return false;
  166.     if (strncmp(vgaInfo.VESASignature,"VESA",4) != 0)
  167.         return false;
  168.  
  169.     /* Copy relevent information from the mode block into our globals.
  170.      * Note that the video mode list _may_ be built in the information
  171.      * block that we have passed, so we _must_ copy this from here
  172.      * into our our storage if we want to continue to use it. Note
  173.      * that we filter out the mode 0x6A, which some BIOSes include as
  174.      * well as the 0x102 mode for 800x600x16.
  175.      */
  176.  
  177.     addr = getLong(vgaInfo.VideoModePtr);
  178.     PM_mapRealPointer(&sel,&off,addr >> 16, addr & 0xFFFF);
  179.     for (i = 0; PM_getWord(sel,off) != 0xFFFF; off += 2,i++) {
  180.         if (PM_getWord(sel,off) != 0x6A)
  181.             modeList[i] = PM_getWord(sel,off);
  182.         }
  183.     modeList[i] = -1;
  184.     memory = getShort(vgaInfo.TotalMemory) * 64;
  185.     addr = getLong(vgaInfo.OEMStringPtr);
  186.     PM_mapRealPointer(&sel,&off,addr >> 16, addr & 0xFFFF);
  187.     PM_memcpynf(OEMString,sel,off,sizeof(OEMString));
  188.  
  189.     /* Determine if the board supports separate read/write banks */
  190.     for (p = modeList; *p != -1; p++) {
  191.         regs.x.ax = 0x4F01;                    /* Get SuperVGA mode info   */
  192.         regs.x.cx = *p;
  193.         CallVBE(®s, &modeInfo, sizeof(modeInfo));
  194.         if (regs.x.ax == 0x004F &&
  195.                 (modeInfo.MemoryModel == 3 || modeInfo.MemoryModel == 4)) {
  196.             modeInfo.WinBAttributes &= 0x7;
  197.             twobanks = (modeInfo.WinBAttributes == 0x3);
  198.  
  199.             /* Check for support of extended page flipping and wide palettes.
  200.              * We need to initialise a video mode to do this.
  201.              */
  202.  
  203.             if (enableSpecialFeatures) {
  204.                 setSuperVGAMode(*p);
  205.                 extendedflipping = setSuperVGADisplayStart(10,10);
  206.                 widedac = set8BitPalette() && set6BitPalette();
  207.                 restoreMode();
  208.                 }
  209.             break;
  210.             }
  211.         }
  212.  
  213.     atexit(exitSuperVGA);    /* Ensure our exit routine is always called    */
  214.  
  215.     return getShort(vgaInfo.VESAVersion);
  216. }
  217.  
  218. PRIVATE void computePageInfo(ModeInfoBlock *modeInfo,int *maxpage,
  219.     long *pagesize)
  220. /****************************************************************************
  221. *
  222. * Function:     computePageInfo
  223. * Parameters:   modeInfo    - Pointer to valid mode information block
  224. *               maxpage     - Number of display pages - 1
  225. *               pagesize    - Size of each logical display page in bytes
  226. *
  227. * Description:  Computes the number of image pages and size of each image
  228. *               page for a specified video mode.
  229. *
  230. ****************************************************************************/
  231. {
  232.     long    memsize,size;
  233.  
  234.     if (!extendedflipping) {
  235.         if (modeInfo->MemoryModel == memPL)
  236.             memsize = 256 * 1024L;
  237.         else memsize = 64 * 1024L;
  238.         }
  239.     else
  240.         memsize = memory * 1024L;
  241.  
  242.     size = (long)getShort(modeInfo->BytesPerScanLine) *
  243.            (long)getShort(modeInfo->YResolution);
  244.     if (modeInfo->BitsPerPixel == 4) {
  245.         /* We have a 16 color video mode, so round up the page size to
  246.          * 8k, 16k, 32k or 64k boundaries depending on how large it is.
  247.          */
  248.  
  249.         size = (size + 0x1FFFL) & 0xFFFFE000L;
  250.         if (size != 0x2000) {
  251.             size = (size + 0x3FFFL) & 0xFFFFC000L;
  252.             if (size != 0x4000) {
  253.                 size = (size + 0x7FFFL) & 0xFFFF8000L;
  254.                 if (size != 0x8000)
  255.                     size = (size + 0xFFFFL) & 0xFFFF0000L;
  256.                 }
  257.             }
  258.         }
  259.     else
  260.         size = (size + 0xFFFFL) & 0xFFFF0000L;
  261.  
  262.     if (modeInfo->MemoryModel == memPL)
  263.         memsize /= 4;
  264.     if (size <= memsize)
  265.         *maxpage = (memsize / size) - 1;
  266.     else
  267.         *maxpage = 0;
  268.     *pagesize = size;
  269. }
  270.  
  271. PUBLIC bool getSuperVGAModeInfo(int mode,int *xres,int *yres,
  272.     int *bytesperline,int *bitsperpixel,int *memmodel,int *maxpage,
  273.     long *pagesize)
  274. /****************************************************************************
  275. *
  276. * Function:     getSuperVGAModeInfo
  277. * Parameters:   mode            - Mode to get information about
  278. *               xres            - Place to store x resolution
  279. *               yres            - Place to store y resolution
  280. *               bytesperline    - Bytes per scanline
  281. *               bitsperpixel    - Place to store bits per pixel (2^n colors)
  282. *               memmodel        - Memory model for mode (planar, packed etc)
  283. *               maxpage         - Number of display pages - 1
  284. *               pagesize        - Size of each logical display page in bytes
  285. * Returns:      True if mode number was valid, false if not.
  286. *
  287. * Description:  Obtains information about a specific video mode from the
  288. *               VBE. You should use this function to find the video mode
  289. *               you wish to set, as the new VBE 2.0 mode numbers may be
  290. *               completely arbitrary.
  291. *
  292. ****************************************************************************/
  293. {
  294.     ModeInfoBlock   modeInfo;
  295.     RMREGS          regs;
  296.  
  297.     if (mode <= 0x13) {
  298.         /* This is a standard VGA mode, so fill in the required information
  299.          * ourselves.
  300.          */
  301.  
  302.         switch (mode) {
  303.             case 0x0D:
  304.                 getShort(modeInfo.XResolution) = 320;
  305.                 getShort(modeInfo.YResolution) = 200;
  306.                 getShort(modeInfo.BytesPerScanLine) = 40;
  307.                 modeInfo.BitsPerPixel = 4;
  308.                 modeInfo.MemoryModel = memPL;
  309.                 break;
  310.             case 0x0E:
  311.                 getShort(modeInfo.XResolution) = 640;
  312.                 getShort(modeInfo.YResolution) = 200;
  313.                 getShort(modeInfo.BytesPerScanLine) = 80;
  314.                 modeInfo.BitsPerPixel = 4;
  315.                 modeInfo.MemoryModel = memPL;
  316.                 break;
  317.             case 0x10:
  318.                 getShort(modeInfo.XResolution) = 640;
  319.                 getShort(modeInfo.YResolution) = 350;
  320.                 getShort(modeInfo.BytesPerScanLine) = 80;
  321.                 modeInfo.BitsPerPixel = 4;
  322.                 modeInfo.MemoryModel = memPL;
  323.                 break;
  324.             case 0x12:
  325.                 getShort(modeInfo.XResolution) = 640;
  326.                 getShort(modeInfo.YResolution) = 480;
  327.                 getShort(modeInfo.BytesPerScanLine) = 80;
  328.                 modeInfo.BitsPerPixel = 4;
  329.                 modeInfo.MemoryModel = memPL;
  330.                 break;
  331.             case 0x13:
  332.                 getShort(modeInfo.XResolution) = 320;
  333.                 getShort(modeInfo.YResolution) = 200;
  334.                 getShort(modeInfo.BytesPerScanLine) = 320;
  335.                 modeInfo.BitsPerPixel = 8;
  336.                 modeInfo.MemoryModel = memPK;
  337.                 break;
  338.             default:
  339.                 return false;
  340.             }
  341.         }
  342.     else {
  343.         /* This is a VESA mode, so call the BIOS to get information about
  344.          * it.
  345.          */
  346.  
  347.         regs.x.ax = 0x4F01;                /* Get mode information         */
  348.         regs.x.cx = mode;
  349.         CallVBE(®s, &modeInfo, sizeof(modeInfo));
  350.         if (regs.x.ax != 0x004F)
  351.             return false;
  352.         if ((getShort(modeInfo.ModeAttributes) & 0x1) == 0)
  353.             return false;
  354.         }
  355.     *xres = getShort(modeInfo.XResolution);
  356.     *yres = getShort(modeInfo.YResolution);
  357.     *bytesperline = getShort(modeInfo.BytesPerScanLine);
  358.     *memmodel = modeInfo.MemoryModel;
  359.     *bitsperpixel = modeInfo.BitsPerPixel;
  360.  
  361.     /* Emulate RGB modes using a 3 3 2 palette arrangement by default */
  362.     redMask = 0x7;        redPos = 5;        redAdjust = 5;
  363.     greenMask = 0x7;    greenPos = 2;    greenAdjust = 5;
  364.     blueMask = 0x3;        bluePos = 0;    blueAdjust = 6;
  365.  
  366.     if (*memmodel == memPK && *bitsperpixel > 8) {
  367.         /* Support old style definitions, which some BIOS'es still use :-( */
  368.         *memmodel = memRGB;
  369.         switch (*bitsperpixel) {
  370.             case 15:
  371.                 redMask = 0x1F;        redPos = 10;    redAdjust = 3;
  372.                 greenMask = 0x1F;    greenPos = 5;    greenAdjust = 3;
  373.                 blueMask = 0x1F;    bluePos = 0;    blueAdjust = 3;
  374.                 break;
  375.             case 16:
  376.                 redMask = 0x1F;        redPos = 11;    redAdjust = 3;
  377.                 greenMask = 0x3F;    greenPos = 5;    greenAdjust = 2;
  378.                 blueMask = 0x1F;    bluePos = 0;    blueAdjust = 3;
  379.                 break;
  380.             case 24:
  381.             case 32:
  382.                 redMask = 0xFF;        redPos = 16;    redAdjust = 0;
  383.                 greenMask = 0xFF;    greenPos = 8;    greenAdjust = 0;
  384.                 blueMask = 0xFF;    bluePos = 0;    blueAdjust = 0;
  385.                 break;
  386.             }
  387.         }
  388.     else if (*memmodel == memRGB) {
  389.         /* Convert the 32k direct color modes of VBE 1.2+ BIOSes to
  390.          * be recognised as 15 bits per pixel modes.
  391.          */
  392.  
  393.         if (*bitsperpixel == 16 && modeInfo.RsvdMaskSize == 1)
  394.             *bitsperpixel = 15;
  395.  
  396.         /* Save direct color info mask positions etc */
  397.  
  398.         redMask = (0xFF >> (redAdjust = 8 - modeInfo.RedMaskSize));
  399.         redPos = modeInfo.RedFieldPosition;
  400.         greenMask = (0xFF >> (greenAdjust = 8 - modeInfo.GreenMaskSize));
  401.         greenPos = modeInfo.GreenFieldPosition;
  402.         blueMask = (0xFF >> (blueAdjust = 8 - modeInfo.BlueMaskSize));
  403.         bluePos = modeInfo.BlueFieldPosition;
  404.         }
  405.     switch (*bitsperpixel) {
  406.         case 15:
  407.         case 16:
  408.             bytesperpixel = 2;
  409.             break;
  410.         case 24:
  411.             bytesperpixel = 3;
  412.             break;
  413.         case 32:
  414.             bytesperpixel = 4;
  415.             break;
  416.         default:
  417.             bytesperpixel = 1;
  418.             break;
  419.         }
  420.     computePageInfo(&modeInfo,maxpage,pagesize);
  421.     return true;
  422. }
  423.  
  424. PUBLIC bool setSuperVGAMode(int mode)
  425. /****************************************************************************
  426. *
  427. * Function:     setSuperVGAMode
  428. * Parameters:   mode    - SuperVGA video mode to set.
  429. * Returns:      True if the mode was set, false if not.
  430. *
  431. * Description:  Attempts to set the specified video mode. This routine
  432. *               assumes that the library and SuperVGA have been initialised
  433. *               with the initSuperVGA() routine first.
  434. *
  435. ****************************************************************************/
  436. {
  437.     ModeInfoBlock   modeInfo;
  438.     RMREGS          regs;
  439.     int             bitsperpixel,memmodel;
  440.  
  441.     regs.x.ax = 0x0F00;
  442.     PM_int86(0x10, ®s, ®s);
  443.     oldMode = regs.x.ax & 0x7F;         /* Save old video mode          */
  444.     old50Lines = false;                 /* Default to 25 line mode      */
  445.     if (oldMode == 0x3) {
  446.         regs.x.ax = 0x1130;
  447.         regs.x.bx = 0;
  448.         regs.x.dx = 0;
  449.         PM_int86(0x10,®s,®s);
  450.         old50Lines = (regs.h.dl == 49);
  451.         }
  452.  
  453.     regs.x.ax = 0x4F02;
  454.     regs.x.bx = mode;
  455.     PM_int86(0x10,®s,®s);          /* Set the video mode           */
  456.     if (regs.x.ax != 0x004F)
  457.         return false;
  458.  
  459.     getSuperVGAModeInfo(mode,&maxx,&maxy,&bytesperline,&bitsperpixel,
  460.         &memmodel,&maxpage,&pagesize);
  461.     maxx--; maxy--;
  462.  
  463.     /* Now set up the vectors to the correct routines for the video
  464.      * mode type.
  465.      */
  466.  
  467.     switch (bitsperpixel) {
  468.         case 4:
  469.             clear = _clear16;
  470.             putPixel = _putPixel16;
  471.             line = _line16;
  472.             maxcolor = defcolor = 15;
  473.             break;
  474.         case 8:
  475.             clear = _clear256;
  476.             putPixel = _putPixel256;
  477.             line = _line256;
  478.             maxcolor = 255;
  479.             defcolor = 15;
  480.             break;
  481.         case 15:
  482.             clear = _clear32k;
  483.             putPixel = _putPixel32k;
  484.             line = _line32k;
  485.             maxcolor = defcolor = 0x7FFF;
  486.             break;
  487.         case 16:
  488.             clear = _clear32k;
  489.             putPixel = _putPixel32k;
  490.             line = _line32k;
  491.             maxcolor = defcolor = 0xFFFF;
  492.             break;
  493.         case 24:
  494.             clear = _clear16m;
  495.             putPixel = _putPixel16m;
  496.             line = _line16m;
  497.             maxcolor = defcolor = 0xFFFFFF;
  498.             break;
  499.         case 32:
  500.             clear = _clear4G;
  501.             putPixel = _putPixel4G;
  502.             line = _line4G;
  503.             maxcolor = defcolor = 0xFFFFFF;
  504.             break;
  505.         }
  506.  
  507.     if (mode <= 0x13) {
  508.         /* This is a normal VGA style mode, so we need to determine the
  509.          * correct information for bank switching from the BIOS
  510.          */
  511.  
  512.         if (mode == 0x13)
  513.             mode = 0x101;
  514.         else
  515.             mode = 0x102;
  516.         }
  517.     regs.x.ax = 0x4F01;                /* Get mode information         */
  518.     regs.x.cx = mode;
  519.     CallVBE(®s, &modeInfo, sizeof(modeInfo));
  520.     bankShift = 0;
  521.     while ((64 >> bankShift) != getShort(modeInfo.WinGranularity))
  522.         bankShift++;
  523.     curBank = -1;
  524.  
  525.     /* Create a pointer to the real mode function for bank switching. In
  526.      * protected mode it is extremely complicated and slow to call a
  527.      * real mode function from low level assembly language, so we simply
  528.      * set the routine to NULL so that the Int 10h interface will be used
  529.      * instead.
  530.      */
  531.     if (_PM_modeType == PM_realMode)
  532.         bankSwitch = (void *)getLong(modeInfo.WinFuncPtr);
  533.     else bankSwitch = NULL;
  534.  
  535.     /* Now set up the vectors to the appropriate bank switching routines.
  536.      * If the Universal VESA VBE is installed, we can move the bank
  537.      * switching routines from there into our own code space for speed
  538.      * (especially under protected mode).
  539.      */
  540.  
  541.     writeBank = readBank = NULL;
  542. #ifdef    PM386
  543.     {
  544.         uint    sel,off;
  545.         RMSREGS    sregs;
  546.  
  547.         regs.x.ax = 0x4F0A;
  548.         regs.x.bx = 0xFE01;
  549.         regs.x.dx = 0x0500;
  550.         PM_int86x(0x10, ®s, ®s, &sregs);
  551.         if (regs.x.ax == 0x004F) {
  552.             PM_mapRealPointer(&sel,&off,sregs.es,regs.x.di);
  553.             writeBank = malloc(regs.x.dx);
  554.             PM_memcpynf(writeBank,sel,off,regs.x.dx);
  555.             }
  556.  
  557.         regs.x.ax = 0x4F0A;
  558.         regs.x.bx = 0xFE01;
  559.         regs.x.dx = 0x0501;
  560.         PM_int86x(0x10, ®s, ®s, &sregs);
  561.         if (regs.x.ax == 0x004F) {
  562.             PM_mapRealPointer(&sel,&off,sregs.es,regs.x.di);
  563.             readBank = malloc(regs.x.dx);
  564.             PM_memcpynf(readBank,sel,off,regs.x.dx);
  565.             }
  566.     }
  567. #endif
  568.  
  569.     oldFS = _setFS(PM_getVGASelector());    /* Set FS to VGA selector    */
  570.     return true;
  571. }
  572.  
  573. PUBLIC void restoreMode(void)
  574. /****************************************************************************
  575. *
  576. * Function:     restoreMode
  577. *
  578. * Description:  Restore the previous video mode in use before the SuperVGA
  579. *               mode was set. This routine will also restore the 50 line
  580. *               display mode if this mode was previously set.
  581. *
  582. ****************************************************************************/
  583. {
  584.     RMREGS    regs;
  585.  
  586.     _setFS(oldFS);                    /* Restore value of FS selector    */
  587.     free(readBank);                    /* Free the relocated reoutines    */
  588.     free(writeBank);                /* if any were allocated        */
  589.     regs.x.ax = oldMode;
  590.     PM_int86(0x10,®s,®s);     /* Set the old video mode       */
  591.     if (old50Lines) {
  592.         regs.x.ax = 0x1112;
  593.         regs.x.bx = 0;
  594.         PM_int86(0x10,®s,®s);    /* Restore 50 line mode         */
  595.         }
  596. }
  597.  
  598. bool setSuperVGADisplayStart(int x,int y)
  599. /****************************************************************************
  600. *
  601. * Function:     setDisplayStart
  602. * Parameters:   x,y - Position of the first pixel to display
  603. * Returns:        True if function was successful.
  604. *
  605. * Description:  Sets the new starting display position to implement
  606. *               hardware scrolling.
  607. *
  608. ****************************************************************************/
  609. {
  610.     RMREGS  regs;
  611.  
  612.     regs.x.ax = 0x4F07;
  613.     regs.x.bx = 0x0000;
  614.     regs.x.cx = x;
  615.     regs.x.dx = y;
  616.     PM_int86(0x10,®s,®s);
  617.     if (regs.x.ax != 0x004F)
  618.         return false;
  619.     return true;
  620. }
  621.  
  622. bool set8BitPalette(void)
  623. /****************************************************************************
  624. *
  625. * Function:        set8BitPalette
  626. * Returns:        True if 8 bit wide palette has been set.
  627. *
  628. * Description:    Attempts to set the system into the 8 bit wide palette
  629. *                mode if supported by the VBE. Returns true on success, false
  630. *                otherwise.
  631. *
  632. ****************************************************************************/
  633. {
  634.     RMREGS  regs;
  635.  
  636.     regs.x.ax = 0x4F08;         /* Set DAC service                      */
  637.     regs.x.bx = 0x0800;         /* BH := 8, BL := 0 (set DAC width)     */
  638.     PM_int86(0x10,®s,®s);
  639.     if (regs.x.ax != 0x004F)
  640.         return false;           /* Function failed, no wide dac         */
  641.     if (regs.h.bh == 6)
  642.         return false;
  643.     regs.x.ax = 0x4F08;
  644.     regs.x.bx = 0x0001;         /* Get DAC width (should now be 8)      */
  645.     PM_int86(0x10,®s,®s);
  646.     if (regs.x.ax != 0x004F)
  647.         return false;
  648.     if (regs.h.bh != 8)
  649.         return false;
  650.     return true;
  651. }
  652.  
  653. bool set6BitPalette(void)
  654. /****************************************************************************
  655. *
  656. * Function:        set6BitPalette
  657. * Returns:        True if 6 bit wide palette has been set.
  658. *
  659. * Description:    Attempts to set the system back into the 6 bit wide palette
  660. *                mode if supported by the VBE. Returns true on success, false
  661. *                otherwise.
  662. *
  663. ****************************************************************************/
  664. {
  665.     RMREGS  regs;
  666.  
  667.     regs.x.ax = 0x4F08;
  668.     regs.x.bx = 0x0600;
  669.     PM_int86(0x10,®s,®s);    /* Restore to 6 bit DAC               */
  670.     if (regs.x.ax != 0x004F)
  671.         return true;
  672.     if (regs.h.bh != 6)
  673.         return false;
  674.     return true;
  675. }
  676.  
  677. void setPalette(int start, int num, palette *palbuf)
  678. /****************************************************************************
  679. *
  680. * Function:        setPalette
  681. * Parameters:    start    - Starting index number
  682. *                num        - Number of entries to program
  683. *                palbuf    - Buffer of palette values to program
  684. *
  685. * Description:    Sets the palette values. The values should be in the
  686. *                range 0-63 if the palette is in the 6 bit mode, or 0-255
  687. *                if the palette is in the 8 bit mode. The palette is
  688. *                programmed via the BIOS.
  689. *
  690. ****************************************************************************/
  691. {
  692.     RMREGS    regs;
  693.     RMSREGS    sregs;
  694.  
  695.     regs.x.ax = 0x1012;
  696.     regs.x.bx = start;
  697.     regs.x.cx = num;
  698.     sregs.es = VESABuf_rseg;
  699.     regs.x.dx = VESABuf_roff;
  700.     PM_memcpyfn(VESABuf_sel,VESABuf_off, palbuf, num * 3);
  701.     PM_int86x(0x10, ®s, ®s, &sregs);
  702. }
  703.  
  704. void getPalette(int start, int num, palette *palbuf)
  705. /****************************************************************************
  706. *
  707. * Function:        getPalette
  708. * Parameters:    start    - Starting index number
  709. *                num        - Number of entries to read
  710. *                red        - Array of red values (0-63 or 0-255)
  711. *                green    - Array of green values (0-63 or 0-255)
  712. *                blue    - Array of blue values (0-63 or 0-255)
  713. *
  714. * Description:    Reads the current palette values.
  715. *
  716. ****************************************************************************/
  717. {
  718.     RMREGS    regs;
  719.     RMSREGS    sregs;
  720.  
  721.     regs.x.ax = 0x1017;
  722.     regs.x.bx = start;
  723.     regs.x.cx = num;
  724.     sregs.es = VESABuf_rseg;
  725.     regs.x.dx = VESABuf_roff;
  726.     PM_int86x(0x10, ®s, ®s, &sregs);
  727.     PM_memcpynf(palbuf, VESABuf_sel,VESABuf_off, num * 3);
  728. }
  729.  
  730. long rgbColor(uchar r,uchar g,uchar b)
  731. /****************************************************************************
  732. *
  733. * Function:     rgbColor
  734. *
  735. * Returns:      Value representing the color. The value is converted from
  736. *               24 bit RGB space into the appropriate color for the
  737. *               video mode.
  738. *
  739. ****************************************************************************/
  740. {
  741.     return ((long)((r >> redAdjust) & redMask) << redPos)
  742.          | ((long)((g >> greenAdjust) & greenMask) << greenPos)
  743.          | ((long)((b >> blueAdjust) & blueMask) << bluePos);
  744. }
  745.  
  746. PUBLIC void _cdecl _EMU_line(int x1,int y1,int x2,int y2,long color)
  747. /****************************************************************************
  748. *
  749. * Function:     line
  750. * Parameters:   x1,y1       - First endpoint of line
  751. *               x2,y2       - Second endpoint of line
  752. *               color       - Color to draw the line in
  753. *
  754. * Description:  Scan convert a line segment using the MidPoint Digital
  755. *               Differential Analyser algorithm.
  756. *
  757. ****************************************************************************/
  758. {
  759.     int     d;                      /* Decision variable                */
  760.     int     dx,dy;                  /* Dx and Dy values for the line    */
  761.     int     Eincr,NEincr;           /* Decision variable increments     */
  762.     int     yincr;                  /* Increment for y values           */
  763.     int     t;                      /* Counters etc.                    */
  764.  
  765.     dx = ABS(x2 - x1);
  766.     dy = ABS(y2 - y1);
  767.  
  768.     if (dy <= dx) {
  769.  
  770.         /* We have a line with a slope between -1 and 1
  771.          *
  772.          * Ensure that we are always scan converting the line from left to
  773.          * right to ensure that we produce the same line from P1 to P0 as the
  774.          * line from P0 to P1.
  775.          */
  776.  
  777.         if (x2 < x1) {
  778.             t = x2; x2 = x1; x1 = t;    /* Swap X coordinates           */
  779.             t = y2; y2 = y1; y1 = t;    /* Swap Y coordinates           */
  780.             }
  781.  
  782.         if (y2 > y1)
  783.             yincr = 1;
  784.         else
  785.             yincr = -1;
  786.  
  787.         d = 2*dy - dx;              /* Initial decision variable value  */
  788.         Eincr = 2*dy;               /* Increment to move to E pixel     */
  789.         NEincr = 2*(dy - dx);       /* Increment to move to NE pixel    */
  790.  
  791.         putPixel(x1,y1,color);      /* Draw the first point at (x1,y1)  */
  792.  
  793.         /* Incrementally determine the positions of the remaining pixels
  794.          */
  795.  
  796.         for (x1++; x1 <= x2; x1++) {
  797.             if (d < 0) {
  798.                 d += Eincr;         /* Choose the Eastern Pixel         */
  799.                 }
  800.             else {
  801.                 d += NEincr;        /* Choose the North Eastern Pixel   */
  802.                 y1 += yincr;        /* (or SE pixel for dx/dy < 0!)     */
  803.                 }
  804.             putPixel(x1,y1,color);  /* Draw the point                   */
  805.             }
  806.         }
  807.     else {
  808.  
  809.         /* We have a line with a slope between -1 and 1 (ie: includes
  810.          * vertical lines). We must swap our x and y coordinates for this.
  811.          *
  812.          * Ensure that we are always scan converting the line from left to
  813.          * right to ensure that we produce the same line from P1 to P0 as the
  814.          * line from P0 to P1.
  815.          */
  816.  
  817.         if (y2 < y1) {
  818.             t = x2; x2 = x1; x1 = t;    /* Swap X coordinates           */
  819.             t = y2; y2 = y1; y1 = t;    /* Swap Y coordinates           */
  820.             }
  821.  
  822.         if (x2 > x1)
  823.             yincr = 1;
  824.         else
  825.             yincr = -1;
  826.  
  827.         d = 2*dx - dy;              /* Initial decision variable value  */
  828.         Eincr = 2*dx;               /* Increment to move to E pixel     */
  829.         NEincr = 2*(dx - dy);       /* Increment to move to NE pixel    */
  830.  
  831.         putPixel(x1,y1,color);      /* Draw the first point at (x1,y1)  */
  832.  
  833.         /* Incrementally determine the positions of the remaining pixels
  834.          */
  835.  
  836.         for (y1++; y1 <= y2; y1++) {
  837.             if (d < 0) {
  838.                 d += Eincr;         /* Choose the Eastern Pixel         */
  839.                 }
  840.             else {
  841.                 d += NEincr;        /* Choose the North Eastern Pixel   */
  842.                 x1 += yincr;        /* (or SE pixel for dx/dy < 0!)     */
  843.                 }
  844.             putPixel(x1,y1,color);  /* Draw the point                   */
  845.             }
  846.         }
  847. }
  848.  
  849. PUBLIC void writeText(int x,int y,char *str,long color)
  850. /****************************************************************************
  851. *
  852. * Function:     writeText
  853. * Parameters:   x,y     - Position to begin drawing string at
  854. *               str     - String to draw
  855. *
  856. * Description:  Draws a string using the BIOS 8x16 video font by plotting
  857. *               each pixel in the characters individually. This should
  858. *               work for all video modes.
  859. *
  860. ****************************************************************************/
  861. {
  862.     uchar           byte;
  863.     int             i,j,k,length,ch;
  864.     uchar              *font;
  865.  
  866.     font = font8x16;
  867.     length = strlen(str);
  868.     for (k = 0; k < length; k++) {
  869.         ch = str[k];
  870.         for (j = 0; j < 16; j++) {
  871.             byte = *(font + ch * 16 + j);
  872.             for (i = 0; i < 8; i++) {
  873.                 if ((byte & 0x80) != 0)
  874.                     putPixel(x+i,y+j,color);
  875.                 byte <<= 1;
  876.                 }
  877.             }
  878.         x += 8;
  879.         }
  880. }
  881.